package com.nio.c5_网络编程.nio;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;

/**
 * @version No one is coming, unless you change yourself!!!
 * @author： pang-yun
 * @date： 2021-05-31 19:31
 */

/**
 * 非阻塞模式之下  需要设置两个地方让其不会停止
 * - serverSocketChannel  设为非阻塞  那么在 serverSocketChannel.accept 建立连接的时候就不会停止
 * - socketChannel       设为非阻塞时  那么 read 读取数据时就不会停止
 * */


//非阻塞模式
@Slf4j
public class NioServer {
    public static void main(String[] args) throws IOException {
        ByteBuffer byteBuffer = ByteBuffer.allocate(32);

        //1.创建服务器、
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false); //======重点：：：将ServerSocketChannel设置为false 即 非阻塞模式
        //2.绑定接口
        ssc.bind(new InetSocketAddress(9999));

        //3.连接集合
        List<SocketChannel> channelsList = new ArrayList<>();

        while (true) {
            // 4. accept 建立与客户端连接，SocketChannel 用来与客户端通信
            SocketChannel socketChannel = ssc.accept(); //非阻塞模式下，如果没有建立连接诶，socketChannel是null,所以下一步判断是否未null
            if (socketChannel != null) {
                log.debug("connected....{}", socketChannel);
                socketChannel.configureBlocking(false);  //非阻塞模式  程序会不断运行 ，即使没有连接  没有连接
                channelsList.add(socketChannel);
            }
            for (SocketChannel channel : channelsList) {
                //5.接收客户端发送的数据
                int read = 0;   //非阻塞线程，线程仍会继续运行，如果没有数据，read返回0
                try {
                    read = channel.read(byteBuffer); // read时 客户端异常关闭 但服务器端已经获取到
                } catch (IOException e) {
                    channel.socket().close();
                    channel.close();
                }
                if (read==-1){
                    channel.close();
                }else if (read > 0) {
                    byteBuffer.flip();
                    while (byteBuffer.hasRemaining()) {
                        byte b = byteBuffer.get();
                        System.out.print((char) b);

                    }
                    byteBuffer.clear();
                    System.out.println();
                    log.debug("after read.....{}", channel);

                }
            }

        }
    }
}
